home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP09.ZIP / CHAP09 / PATRON / DOCUMENT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-23  |  29.0 KB  |  1,301 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Modifications for Chapter 9
  4.  *
  5.  * Implementation of the CPatronDoc derivation of CDocument that
  6.  * manages pages for us.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include <memory.h>
  19. #include "patron.h"
  20.  
  21.  
  22.  
  23. /*
  24.  * CPatronDoc::CPatronDoc
  25.  * CPatronDoc::~CPatronDoc
  26.  *
  27.  * Constructor Parameters:
  28.  *  hInst           HINSTANCE of the application.
  29.  */
  30.  
  31. CPatronDoc::CPatronDoc(HINSTANCE hInst)
  32.     : CDocument(hInst)
  33.     {
  34.     m_pPG=NULL;
  35.     m_lVer=VERSIONCURRENT;
  36.     m_pIStorage=NULL;
  37.     m_fPrintSetup=TRUE;
  38.     m_pDropTarget=NULL;
  39.  
  40.     //CHAPTER9MOD
  41.     m_cfEmbeddedObject  =RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  42.     m_cfObjectDescriptor=RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  43.     //End CHAPTER9MOD
  44.  
  45.     return;
  46.     }
  47.  
  48.  
  49. CPatronDoc::~CPatronDoc(void)
  50.     {
  51.     if (NULL!=m_pDropTarget)
  52.         {
  53.         RevokeDragDrop(m_hWnd);
  54.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, FALSE, TRUE);
  55.         m_pDropTarget->Release();
  56.         }
  57.  
  58.     if (NULL!=m_pPG)
  59.         delete m_pPG;
  60.  
  61.     if (NULL!=m_pIStorage)
  62.         m_pIStorage->Release();
  63.  
  64.     CoFreeUnusedLibraries();
  65.     return;
  66.     }
  67.  
  68.  
  69.  
  70.  
  71.  
  72. /*
  73.  * CPatronDoc::FInit
  74.  *
  75.  * Purpose:
  76.  *  Initializes an already created document window.  The client actually
  77.  *  creates the window for us, then passes that here for further
  78.  *  initialization.
  79.  *
  80.  * Parameters:
  81.  *  pDI             LPDOCUMENTINIT containing initialization parameters.
  82.  *
  83.  * Return Value:
  84.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  85.  */
  86.  
  87. BOOL CPatronDoc::FInit(LPDOCUMENTINIT pDI)
  88.     {
  89.     //Change the stringtable range to our customization.
  90.     pDI->idsMin=IDS_DOCUMENTMIN;
  91.     pDI->idsMax=IDS_DOCUMENTMAX;
  92.  
  93.     //Do default initialization
  94.     if (!CDocument::FInit(pDI))
  95.         return FALSE;
  96.  
  97.     //Pages are created when we get a ::ULoad later.
  98.     return TRUE;
  99.     }
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106. /*
  107.  * CPatronDoc::FMessageHook
  108.  *
  109.  * Purpose:
  110.  *  Processes WM_SIZE for the document so we can resize the Pages window.
  111.  *
  112.  * Parameters:
  113.  *  <WndProc Parameters>
  114.  *  pLRes           LRESULT FAR * in which to store the return value
  115.  *                  for the message.
  116.  *
  117.  * Return Value:
  118.  *  BOOL            TRUE to prevent further processing, FALSE otherwise.
  119.  */
  120.  
  121. BOOL CPatronDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  122.     , LPARAM lParam, LRESULT FAR *pLRes)
  123.     {
  124.     UINT        dx, dy;
  125.     RECT        rc;
  126.  
  127.     if (WM_SIZE==iMsg && NULL!=m_pPG)
  128.         {
  129.         dx=LOWORD(lParam);
  130.         dy=HIWORD(lParam);
  131.  
  132.         //Resize the Pages window to fit the new client area of the document
  133.         GetClientRect(hWnd, &rc);
  134.         m_pPG->RectSet(&rc, FALSE);
  135.         }
  136.  
  137.     /*
  138.      * We return FALSE even on WM_SIZE so we can let the default procedure
  139.      * handle maximized MDI child windows appropriately.
  140.      */
  141.     return FALSE;
  142.     }
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149.  
  150.  
  151. /*
  152.  * CPatronDoc::Clear
  153.  *
  154.  * Purpose:
  155.  *  Sets all contents in the document back to defaults with no filename.
  156.  *
  157.  * Paramters:
  158.  *  None
  159.  *
  160.  * Return Value:
  161.  *  None
  162.  */
  163.  
  164. void CPatronDoc::Clear(void)
  165.     {
  166.     //Completely reset the pages
  167.     m_pPG->FIStorageSet(NULL, FALSE, FALSE);
  168.  
  169.     CDocument::Clear();
  170.     m_lVer=VERSIONCURRENT;
  171.     return;
  172.     }
  173.  
  174.  
  175.  
  176.  
  177. /*
  178.  * CPatronDoc::FDirtyGet
  179.  *
  180.  * Purpose:
  181.  *  Returns the current dirty status of the document.
  182.  *
  183.  * Parameters:
  184.  *  None
  185.  *
  186.  * Return Value:
  187.  *  BOOL            TRUE if the file is clean, FALSE otherwise.
  188.  */
  189.  
  190. BOOL CPatronDoc::FDirtyGet()
  191.     {
  192.     BOOL    fPageDirty;
  193.  
  194.     fPageDirty=m_pPG->FIsDirty();
  195.     return m_fDirty | fPageDirty;
  196.     }
  197.  
  198.  
  199.  
  200.  
  201.  
  202. /*
  203.  * CPatronDoc::Delete
  204.  *
  205.  * Purpose:
  206.  *  Removed the current object from the document.
  207.  *
  208.  * Paramters:
  209.  *  None
  210.  *
  211.  * Return Value:
  212.  *  None
  213.  */
  214.  
  215. void CPatronDoc::Delete(void)
  216.     {
  217.     if (NULL!=m_pPG)
  218.         m_pPG->TenantDestroy();
  219.  
  220.     CoFreeUnusedLibraries();
  221.     return;
  222.     }
  223.  
  224.  
  225.  
  226. /*
  227.  * CPatronDoc::FQueryPrinterSetup
  228.  *
  229.  * Purpose:
  230.  *  Returns whether or not the Printer Setup menu item can be
  231.  *  enabled.  Once you create a tenant in any page, Printer Setup
  232.  *  is voided simply to keep this sample simple, that is, we don't
  233.  *  have to worry about reorganizing potentially large amounts
  234.  *  of layout after we start plopping down objects.
  235.  *
  236.  * Parameters:
  237.  *  None
  238.  *
  239.  * Return Value:
  240.  *  BOOL            TRUE to enable the menu, FALSE otherwise.
  241.  */
  242.  
  243. BOOL CPatronDoc::FQueryPrinterSetup(void)
  244.     {
  245.     return m_fPrintSetup;
  246.     }
  247.  
  248.  
  249.  
  250.  
  251.  
  252. /*
  253.  * CPatronDoc::FQueryObjectSelected
  254.  *
  255.  * Purpose:
  256.  *  Returns whether or not there is an object selected in this
  257.  *  document for Cut, Copy, Delete functions.
  258.  *
  259.  * Parameters:
  260.  *  hMenu           HMENU of the Edit menu.
  261.  *
  262.  * Return Value:
  263.  *  BOOL            TRUE if we have an object, FALSE otherwise.
  264.  */
  265.  
  266. BOOL CPatronDoc::FQueryObjectSelected(HMENU hMenu)
  267.     {
  268.     return m_pPG->FQueryObjectSelected(hMenu);
  269.     }
  270.  
  271.  
  272.  
  273.  
  274.  
  275. /*
  276.  * CPatronDoc::ULoad
  277.  *
  278.  * Purpose:
  279.  *  Loads a given document without any user interface overwriting the
  280.  *  previous contents of the editor.
  281.  *
  282.  * Parameters:
  283.  *  fChangeFile     BOOL indicating if we're to update the window title
  284.  *                  and the filename from using this file.
  285.  *  pszFile         LPSTR to the filename to load.  Could be NULL for
  286.  *                  an untitled document.
  287.  *
  288.  * Return Value:
  289.  *  UINT            An error value from DOCERR_*
  290.  */
  291.  
  292.  
  293. UINT CPatronDoc::ULoad(BOOL fChangeFile, LPSTR pszFile)
  294.     {
  295.     RECT        rc;
  296.     LPSTORAGE   pIStorage;
  297.     HRESULT     hr;
  298.     CLSID       clsID;
  299.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  300.  
  301.     if (NULL==pszFile)
  302.         {
  303.         //Create a new temp file.
  304.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE | STGM_DELETEONRELEASE
  305.             , 0, &pIStorage);
  306.  
  307.         //Mark this as one of our class since we check with ReadClassStg below.
  308.         if (SUCCEEDED(hr))
  309.             WriteClassStg(pIStorage, CLSID_PatronPages);
  310.         }
  311.     else
  312.         {
  313.         hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  314.         }
  315.  
  316.     if (FAILED(hr))
  317.         return DOCERR_COULDNOTOPEN;
  318.  
  319.     //Check if this is our type of file and exit if not.
  320.     hr=ReadClassStg(pIStorage, &clsID);
  321.  
  322.     if (FAILED(hr) || !IsEqualCLSID(clsID, CLSID_PatronPages))
  323.         {
  324.         pIStorage->Release();
  325.         return DOCERR_READFAILURE;
  326.         }
  327.  
  328.     //Attempt to create our contained Pages window.
  329.     m_pPG=new CPages(m_hInst, m_cf);
  330.     GetClientRect(m_hWnd, &rc);
  331.  
  332.     if (!m_pPG->FInit(m_hWnd, &rc, WS_CHILD | WS_VISIBLE, ID_PAGES, NULL))
  333.         {
  334.         pIStorage->Release();
  335.         return DOCERR_READFAILURE;
  336.         }
  337.  
  338.     if (!m_pPG->FIStorageSet(pIStorage, FALSE, (BOOL)(NULL==pszFile)))
  339.         {
  340.         pIStorage->Release();
  341.         return DOCERR_READFAILURE;
  342.         }
  343.  
  344.     //Open the window up for drag-drop
  345.     m_pDropTarget=new CDropTarget(this);
  346.  
  347.     if (NULL!=m_pDropTarget)
  348.         {
  349.         m_pDropTarget->AddRef();
  350.         RegisterDragDrop(m_hWnd, (LPDROPTARGET)m_pDropTarget);
  351.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, TRUE, FALSE);
  352.         }
  353.  
  354.     m_pIStorage=pIStorage;
  355.     Rename(pszFile);
  356.  
  357.     //Do initial setup if this is a new file, otherwise Pages handles things.
  358.     if (NULL==pszFile)
  359.         {
  360.         //Go initialize the Pages for the default printer.
  361.         if (!PrinterSetup(NULL, TRUE))
  362.             return DOCERR_COULDNOTOPEN;
  363.  
  364.         //Go create an initial page.
  365.         m_pPG->PageInsert(0);
  366.         }
  367.     else
  368.         m_fPrintSetup=FALSE;    //Can't change an already saved configuration
  369.  
  370.     FDirtySet(FALSE);
  371.     return DOCERR_NONE;
  372.     }
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380. /*
  381.  * CPatronDoc::USave
  382.  *
  383.  * Purpose:
  384.  *  Writes the file to a known filename, requiring that the user has
  385.  *  previously used FileOpen or FileSaveAs in order to have a filename.
  386.  *
  387.  * Parameters:
  388.  *  uType           UINT indicating the type of file the user requested
  389.  *                  to save in the File Save As dialog.
  390.  *  pszFile         LPSTR under which to save.  If NULL, use the current name.
  391.  *
  392.  * Return Value:
  393.  *  UINT            An error value from DOCERR_*
  394.  */
  395.  
  396. UINT CPatronDoc::USave(UINT uType, LPSTR pszFile)
  397.     {
  398.     HRESULT     hr;
  399.     LPSTORAGE   pIStorage;
  400.  
  401.     //Save or Save As with the same file is just a commit.
  402.     if (NULL==pszFile || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  403.         {
  404.         WriteFmtUserTypeStg(m_pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  405.  
  406.         //Insure pages are up to date.
  407.         m_pPG->FIStorageUpdate(FALSE);
  408.  
  409.         //Commit everyting
  410.         m_pIStorage->Commit(STGC_ONLYIFCURRENT);
  411.  
  412.         FDirtySet(FALSE);
  413.         return DOCERR_NONE;
  414.         }
  415.  
  416.     /*
  417.      * When we're given a name, open the storage, creating it new if
  418.      * it does not exist or overwriting the old one.  Then ::CopyTo
  419.      * from the current to the new, ::Commit the new, then ::Release
  420.      * the old.
  421.      */
  422.  
  423.     hr=StgCreateDocfile(pszFile, STGM_TRANSACTED | STGM_READWRITE
  424.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  425.  
  426.     if (FAILED(hr))
  427.         return DOCERR_COULDNOTOPEN;
  428.  
  429.     WriteClassStg(pIStorage, CLSID_PatronPages);
  430.     WriteFmtUserTypeStg(pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  431.  
  432.     //Insure all pages are up-to-date.
  433.     m_pPG->FIStorageUpdate(TRUE);
  434.  
  435.     //This also copies the CLSID we stuff in here on file creation.
  436.     hr=m_pIStorage->CopyTo(NULL, NULL, NULL, pIStorage);
  437.  
  438.     if (FAILED(hr))
  439.         {
  440.         pIStorage->Release();
  441.         return DOCERR_WRITEFAILURE;
  442.         }
  443.  
  444.     pIStorage->Commit(STGC_ONLYIFCURRENT);
  445.  
  446.     /*
  447.      * Revert changes on the original storage.  If this was a temp file,
  448.      * it's deleted since we used STGM_DELETEONRELEASE.
  449.      */
  450.     m_pIStorage->Release();
  451.  
  452.     //Make this new storage current
  453.     m_pIStorage=pIStorage;
  454.     m_pPG->FIStorageSet(pIStorage, TRUE, FALSE);
  455.  
  456.     FDirtySet(FALSE);
  457.     Rename(pszFile);    //Update caption bar.
  458.  
  459.     return DOCERR_NONE;
  460.     }
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469. /*
  470.  * CPatronDoc::FClip
  471.  *
  472.  * Purpose:
  473.  *  Places a private format, a metafile, and a bitmap of the display
  474.  *  on the clipboard, optionally implementing Cut by deleting the
  475.  *  data in the current window after rendering.
  476.  *
  477.  * Parameters:
  478.  *  hWndFrame       HWND of the main window.
  479.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  480.  *
  481.  * Return Value:
  482.  *  BOOL            TRUE if successful, FALSE otherwise.
  483.  */
  484.  
  485. BOOL CPatronDoc::FClip(HWND hWndFrame, BOOL fCut)
  486.     {
  487.     if (NULL==m_pPG)
  488.         return FALSE;
  489.  
  490.     return m_pPG->TenantClip(fCut);
  491.     }
  492.  
  493.  
  494.  
  495.  
  496.  
  497. /*
  498.  * CPatronDoc::FPaste
  499.  *
  500.  * Purpose:
  501.  *  Retrieves the private data format from the clipboard and sets it
  502.  *  to the current figure in the editor window.
  503.  *
  504.  *  Note that if this function is called, then the clipboard format
  505.  *  is available because the Paste menu item is only enabled if the
  506.  *  format is present.
  507.  *
  508.  * Parameters:
  509.  *  hWndFrame       HWND of the main window.
  510.  *
  511.  * Return Value:
  512.  *  BOOL            TRUE if successful, FALSE otherwise.
  513.  */
  514.  
  515. BOOL CPatronDoc::FPaste(HWND hWndFrame)
  516.     {
  517.     LPDATAOBJECT    pIDataObject;
  518.     BOOL            fRet=FALSE;
  519.     FORMATETC       fe;
  520.     TENANTTYPE      tType;
  521.  
  522.     if (NULL==m_pPG)
  523.         return FALSE;
  524.  
  525.     if (FAILED(OleGetClipboard(&pIDataObject)))
  526.         return FALSE;
  527.  
  528.     //Go get the type and format we *can* paste, then actually paste it.
  529.     if (FQueryPasteFromData(pIDataObject, &fe, &tType))
  530.         {
  531.         //CHAPTER9MOD
  532.         fRet=FPasteFromData(pIDataObject, &fe, tType, NULL, 0L, TRUE);
  533.         //End CHAPTER9MOD
  534.         }
  535.  
  536.     pIDataObject->Release();
  537.     return fRet;
  538.     }
  539.  
  540.  
  541.  
  542.  
  543. /*
  544.  * CPatronDoc::FQueryPaste
  545.  *
  546.  * Purpose:
  547.  *  Determines if we can paste data from the clipboard.
  548.  *
  549.  * Parameters:
  550.  *  None
  551.  *
  552.  * Return Value:
  553.  *  BOOL            TRUE if data is available, FALSE otherwise.
  554.  */
  555.  
  556. BOOL CPatronDoc::FQueryPaste(void)
  557.     {
  558.     LPDATAOBJECT    pIDataObject;
  559.     BOOL            fRet;
  560.  
  561.     if (FAILED(OleGetClipboard(&pIDataObject)))
  562.         return FALSE;
  563.  
  564.     fRet=FQueryPasteFromData(pIDataObject, NULL, NULL);
  565.     pIDataObject->Release();
  566.     return fRet;
  567.     }
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574. /*
  575.  * CPatronDoc::FPasteSpecial
  576.  *
  577.  * Purpose:
  578.  *  Retrieves a specific data format from the clipboard and sends it to
  579.  *  the editor window appropriately.
  580.  *
  581.  *  Note that if this function is called, then the appropriate format
  582.  *  is available because the Paste menu item is only enabled if the
  583.  *  format is present.
  584.  *
  585.  * Parameters:
  586.  *  hWndFrame       HWND of the main window
  587.  *
  588.  * Return Value:
  589.  *  BOOL            TRUE if successful, FALSE otherwise.
  590.  */
  591.  
  592. BOOL CPatronDoc::FPasteSpecial(HWND hWndFrame)
  593.     {
  594.     OLEUIPASTESPECIAL   ps;
  595.     //CHAPTER9MOD
  596.     OLEUIPASTEENTRY     rgPaste[5];
  597.     DWORD               dwData=0;
  598.     //End CHAPTER9MOD
  599.     UINT                uTemp;
  600.     BOOL                fRet=FALSE;
  601.  
  602.     if (NULL==m_pPG)
  603.         return FALSE;
  604.  
  605.     _fmemset(&ps, 0, sizeof(ps));
  606.  
  607.     if (FAILED(OleGetClipboard(&ps.lpSrcDataObj)))
  608.         return FALSE;
  609.  
  610.     ps.cbStruct=sizeof(ps);
  611.     ps.hWndOwner=hWndFrame;
  612.  
  613.     ps.dwFlags=PSF_SELECTPASTE;
  614.     ps.arrPasteEntries=rgPaste;
  615.  
  616.     //CHAPTER9MOD
  617.     ps.cPasteEntries=5;
  618.  
  619.     //Set up Paste Special descriptor arrays.
  620.     SETDefFormatEtc(rgPaste[0].fmtetc, m_cf, TYMED_HGLOBAL);
  621.     rgPaste[0].lpstrFormatName=PSZ(IDS_CLIPBOARDFORMAT);
  622.     rgPaste[0].lpstrResultText=PSZ(IDS_PASTEASPATRON);
  623.     rgPaste[0].dwFlags=OLEUIPASTE_PASTEONLY;
  624.  
  625.     //Embedded objects can be iconic displays if the user wants.
  626.     SETDefFormatEtc(rgPaste[1].fmtetc, m_cfEmbeddedObject, TYMED_ISTORAGE);
  627.     rgPaste[1].lpstrFormatName="%s Object";
  628.     rgPaste[1].lpstrResultText="%s Object";
  629.  
  630.     /*
  631.      * CAUTION:  Use OLEUI_PASTE with embedded objects or else
  632.      * this item will not show up in the dialog.  I learned this the
  633.      * hard way (that is, after about 6 hours of pulling hair!).
  634.      */
  635.     rgPaste[1].dwFlags=OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON;
  636.  
  637.  
  638.     SETDefFormatEtc(rgPaste[2].fmtetc, CF_METAFILEPICT, TYMED_MFPICT);
  639.     rgPaste[2].lpstrFormatName=PSZ(IDS_PASTEMETAFILE);
  640.     rgPaste[2].lpstrResultText=PSZ(IDS_PASTEASMETAFILE);
  641.     rgPaste[2].dwFlags=OLEUIPASTE_PASTEONLY;
  642.  
  643.     SETDefFormatEtc(rgPaste[3].fmtetc, CF_DIB, TYMED_HGLOBAL);
  644.     rgPaste[3].lpstrFormatName=PSZ(IDS_PASTEDIB);
  645.     rgPaste[3].lpstrResultText=PSZ(IDS_PASTEASDIB);
  646.     rgPaste[3].dwFlags=OLEUIPASTE_PASTEONLY;
  647.  
  648.     SETDefFormatEtc(rgPaste[4].fmtetc, CF_BITMAP, TYMED_GDI);
  649.     rgPaste[4].lpstrFormatName=PSZ(IDS_PASTEBITMAP);
  650.     rgPaste[4].lpstrResultText=PSZ(IDS_PASTEASBITMAP);
  651.     rgPaste[4].dwFlags=OLEUIPASTE_PASTEONLY;
  652.  
  653.     uTemp=OleUIPasteSpecial(&ps);
  654.  
  655.     if (OLEUI_OK==uTemp)
  656.         {
  657.         UINT        i=ps.nSelectedIndex;
  658.         TENANTTYPE  tType;
  659.  
  660.         if (1==ps.nSelectedIndex)
  661.             tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  662.         else
  663.             tType=TENANTTYPE_STATIC;
  664.  
  665.         //Handle iconic aspects...
  666.         if ((1==i) && (PSF_CHECKDISPLAYASICON & ps.dwFlags)
  667.             && NULL!=ps.hMetaPict)
  668.             {
  669.             rgPaste[i].fmtetc.dwAspect=DVASPECT_ICON;
  670.             dwData=(DWORD)(UINT)ps.hMetaPict;
  671.             }
  672.  
  673.         fRet=FPasteFromData(ps.lpSrcDataObj, &rgPaste[i].fmtetc
  674.             , tType, NULL, dwData, FALSE);
  675.  
  676.         //Always free this regardless of what we do with it.
  677.         if (NULL!=ps.hMetaPict)
  678.             OleUIMetafilePictIconFree(ps.hMetaPict);
  679.  
  680.         }
  681.     //End CHAPTER9MOD
  682.  
  683.     ps.lpSrcDataObj->Release();
  684.     return fRet;
  685.     }
  686.  
  687.  
  688.  
  689.  
  690. /*
  691.  * CPatronDoc::FQueryPasteFromData
  692.  * (Protected)
  693.  *
  694.  * Purpose:
  695.  *  Determines if we can paste data from a data object.
  696.  *
  697.  * Parameters:
  698.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  699.  *  pFE             LPFORMATETC in which to return the first format
  700.  *                  we can use.  Ignored if NULL.
  701.  *  ptType          LPTENANTTYPE in which to store the type of object we
  702.  *                  can paste.  Ignored if NULL.
  703.  *
  704.  * Return Value:
  705.  *  BOOL            TRUE if data is available, FALSE otherwise.
  706.  */
  707.  
  708. BOOL CPatronDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject
  709.     , LPFORMATETC pFE, LPTENANTTYPE ptType)
  710.     {
  711.     FORMATETC       fe;
  712.     //CHAPTER9MOD
  713.     HRESULT         hr, hr2;
  714.     //End CHAPTER9MOD
  715.  
  716.     //Default is static
  717.     if (NULL!=(LPVOID)ptType)
  718.         *ptType=TENANTTYPE_STATIC;
  719.  
  720.     //Any of our specific data here?
  721.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  722.     hr=pIDataObject->QueryGetData(&fe);
  723.  
  724.     //CHAPTER9MOD
  725.     //If embedded object data is available, set the appropriate type
  726.     hr2=OleQueryCreateFromData(pIDataObject);
  727.  
  728.     if (NOERROR==hr2)
  729.         {
  730.         if (NULL!=pFE)
  731.             {
  732.             /*
  733.              * Default to content.  FPaste will use CF_OBJECTDESCRIPTOR
  734.              * to figure the actual aspect.
  735.              */
  736.             SETDefFormatEtc(*pFE, m_cfEmbeddedObject, TYMED_ISTORAGE);
  737.             }
  738.  
  739.         if (NULL!=(LPVOID)ptType)
  740.             *ptType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  741.  
  742.         /*
  743.          * Return now if PatronObject wasn't available, otherwise
  744.          * break out so that pFE gets PatronObject format.
  745.          */
  746.         if (NOERROR!=hr)
  747.             return TRUE;
  748.         }
  749.  
  750.  
  751.     if (NOERROR!=hr && NOERROR!=hr2)
  752.     //End CHAPTER9MOD
  753.         {
  754.         //Try metafile, DIB, then bitmap, setting fe each time for TenantCreate
  755.         SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
  756.         hr=pIDataObject->QueryGetData(&fe);
  757.  
  758.         if (NOERROR!=hr)
  759.             {
  760.             SETDefFormatEtc(fe, CF_DIB, TYMED_HGLOBAL);
  761.             hr=pIDataObject->QueryGetData(&fe);
  762.  
  763.             if (NOERROR!=hr)
  764.                 {
  765.                 SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  766.                 hr=pIDataObject->QueryGetData(&fe);
  767.                 }
  768.             }
  769.         }
  770.  
  771.     if (NOERROR==hr && NULL!=pFE)
  772.         *pFE=fe;
  773.  
  774.     return (NOERROR==hr);
  775.     }
  776.  
  777.  
  778.  
  779.  
  780.  
  781. /*
  782.  * CPatronDoc::FPasteFromData
  783.  * (Protected)
  784.  *
  785.  * Purpose:
  786.  *  Retrieves the private data format from a data object and sets it
  787.  *  to the current figure in the editor window.
  788.  *
  789.  * Parameters:
  790.  *  pIDataObject    LPDATAOBJECT from which to paste.
  791.  *  pFE             LPFORMATETC to use in the paste. Cannot be NULL.
  792.  *  tType           TENANTTYPE to paste.
  793.  *  ppo             LPPATRONOBJECT containing placement data.
  794.  *  dwData          DWORD extra data sensitive to tType
  795.  *  fUseObjDesc     BOOL indicating if we're to use CF_OBJECTDESCRIPTOR
  796.  *                  format for determining the aspect of the object if
  797.  *                  the format is available.
  798.  *
  799.  * Return Value:
  800.  *  BOOL            TRUE if successful, FALSE otherwise.
  801.  */
  802.  
  803. //CHAPTER9MOD
  804. BOOL CPatronDoc::FPasteFromData(LPDATAOBJECT pIDataObject, LPFORMATETC pFE
  805.     , TENANTTYPE tType, LPPATRONOBJECT ppo, DWORD dwData, BOOL fUseObjDesc)
  806. //End CHAPTER9MOD
  807.     {
  808.     BOOL                fRet;
  809.     HRESULT             hr;
  810.     PATRONOBJECT        po;
  811.     STGMEDIUM           stm;
  812.     //CHAPTER9MOD
  813.     LPOBJECTDESCRIPTOR  pOD;
  814.     FORMATETC           fe;
  815.     BOOL                fRelease=FALSE;
  816.     //End CHAPTER9MOD
  817.  
  818.     if (NULL==pFE)
  819.         return FALSE;
  820.  
  821.     //If we're not given any placement data, see if we can retrieve it
  822.     if (pFE->cfFormat==m_cf && NULL==ppo)
  823.         {
  824.         hr=pIDataObject->GetData(pFE, &stm);
  825.  
  826.         if (SUCCEEDED(hr))
  827.             {
  828.             ppo=(LPPATRONOBJECT)GlobalLock(stm.hGlobal);
  829.  
  830.             po=*ppo;
  831.             ppo=&po;
  832.  
  833.             //CHAPTER9MOD
  834.             //If there's an object here, make sure the type is right.
  835.             if (ppo->fe.cfFormat==m_cfEmbeddedObject)
  836.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  837.             //End CHAPTER9MOD
  838.  
  839.             GlobalUnlock(stm.hGlobal);
  840.             ReleaseStgMedium(&stm);
  841.             }
  842.         }
  843.  
  844.     //CHAPTER9MOD
  845.     /*
  846.      * If we're told to look at CF_OBJECTDESCRIPTOR, then try to get the
  847.      * data and copy the aspect out of it.  We're not interested in any
  848.      * other part of it, however.
  849.      */
  850.     if (fUseObjDesc)
  851.         {
  852.         SETDefFormatEtc(fe, m_cfObjectDescriptor, TYMED_HGLOBAL);
  853.  
  854.         if (SUCCEEDED(pIDataObject->GetData(&fe, &stm)))
  855.             {
  856.             pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stm.hGlobal);
  857.             pFE->dwAspect=pOD->dwDrawAspect;
  858.  
  859.             if (NULL!=ppo)
  860.                 ppo->fe.dwAspect=pFE->dwAspect;
  861.  
  862.             GlobalUnlock(stm.hGlobal);
  863.             ReleaseStgMedium(&stm);
  864.  
  865.             /*
  866.              * Furthermore, if pFE->dwAspect is DVASPECT_ICON, get the
  867.              * metafile which will always be the icon representation.
  868.              */
  869.             SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
  870.                 , TYMED_MFPICT, -1);
  871.  
  872.             if (SUCCEEDED(pIDataObject->GetData(&fe, &stm)))
  873.                 {
  874.                 dwData=(DWORD)(UINT)stm.hGlobal;
  875.                 fRelease=TRUE;
  876.                 }
  877.             }
  878.         }
  879.     //End CHAPTER9MOD
  880.  
  881.     fRet=m_pPG->TenantCreate(tType, (LPVOID)pIDataObject, pFE, ppo, dwData);
  882.  
  883.     //CHAPTER9MOD
  884.     //Release the stm from the last GetData
  885.     if (fRelease)
  886.         ReleaseStgMedium(&stm);
  887.     //End CHAPTER9MOD
  888.  
  889.     if (fRet)
  890.         {
  891.         //Disable Printer Setup once we've created a tenant.
  892.         m_fPrintSetup=FALSE;
  893.         FDirtySet(TRUE);
  894.         }
  895.  
  896.     return fRet;
  897.     }
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904. /*
  905.  * CPatronDoc::Print
  906.  *
  907.  * Purpose:
  908.  *  Prints the current document.
  909.  *
  910.  * Parameters:
  911.  *  hWndFrame       HWND of the frame to use for dialog parents.
  912.  *
  913.  * Return Value:
  914.  *  BOOL            TRUE if printing happened, FALSE if it didn't start
  915.  *                  or didn't complete.
  916.  */
  917.  
  918. BOOL CPatronDoc::Print(HWND hWndFrame)
  919.     {
  920.     PRINTDLG        pd;
  921.     BOOL            fSuccess;
  922.  
  923.     memset(&pd, 0, sizeof(PRINTDLG));
  924.     pd.lStructSize=sizeof(PRINTDLG);
  925.     pd.hwndOwner  =hWndFrame;
  926.     pd.nCopies    =1;
  927.     pd.nFromPage  =-1;
  928.     pd.nToPage    =-1;
  929.     pd.nMinPage   =1;
  930.     pd.nMaxPage   =m_pPG->NumPagesGet();
  931.  
  932.     //Get the current document printer settings
  933.     pd.hDevMode=m_pPG->DevModeGet();
  934.  
  935.     pd.Flags=PD_RETURNDC | PD_ALLPAGES | PD_COLLATE
  936.         | PD_HIDEPRINTTOFILE | PD_NOSELECTION;
  937.  
  938.     if (!PrintDlg(&pd))
  939.         return FALSE;
  940.  
  941.     //Make sure the Pages knows about any printer changes.
  942.     if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
  943.         {
  944.         GlobalFree(pd.hDevMode);
  945.         GlobalFree(pd.hDevNames);
  946.         return FALSE;
  947.         }
  948.  
  949.     //Go do the actual printing.
  950.     fSuccess=m_pPG->Print(pd.hDC, PSZ(IDS_DOCUMENTNAME), pd.Flags
  951.         , pd.nFromPage, pd.nToPage, pd.nCopies);
  952.  
  953.     if (!fSuccess)
  954.         MessageBox(m_hWnd, PSZ(IDS_PRINTERROR), PSZ(IDS_DOCUMENTCAPTION), MB_OK);
  955.  
  956.     return fSuccess;
  957.     }
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964. /*
  965.  * CPatronDoc::PrinterSetup
  966.  *
  967.  * Purpose:
  968.  *  Selects a new printer and options for this document.
  969.  *
  970.  * Parameters:
  971.  *  hWndFrame       HWND of the frame to use for dialog parents.
  972.  *  fDefault        BOOL to avoid any dialog and just use the default.
  973.  *
  974.  * Return Value:
  975.  *  UINT            Undefined
  976.  *
  977.  */
  978.  
  979. UINT CPatronDoc::PrinterSetup(HWND hWndFrame, BOOL fDefault)
  980.     {
  981.     PRINTDLG        pd;
  982.  
  983.     //Attempt to get printer metrics for the default printer.
  984.     memset(&pd, 0, sizeof(PRINTDLG));
  985.     pd.lStructSize=sizeof(PRINTDLG);
  986.  
  987.     if (fDefault)
  988.         pd.Flags=PD_RETURNDEFAULT;
  989.     else
  990.         {
  991.         pd.hwndOwner=hWndFrame;
  992.         pd.Flags=PD_PRINTSETUP;
  993.  
  994.         //Get the current document printer settings
  995.         pd.hDevMode=m_pPG->DevModeGet();
  996.         }
  997.  
  998.     if (!PrintDlg(&pd))
  999.         return FALSE;
  1000.  
  1001.     if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
  1002.         {
  1003.         GlobalFree(pd.hDevNames);
  1004.         GlobalFree(pd.hDevMode);
  1005.         return FALSE;
  1006.         }
  1007.  
  1008.     FDirtySet(TRUE);
  1009.     return 1;
  1010.     }
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018. /*
  1019.  * CPatronDoc::NewPage
  1020.  *
  1021.  * Purpose:
  1022.  *  Creates a new page in the document's pages control after the
  1023.  *  current page.
  1024.  *
  1025.  * Parameters:
  1026.  *  None
  1027.  *
  1028.  * Return Value:
  1029.  *  UINT            Index of the new page.
  1030.  */
  1031.  
  1032. UINT CPatronDoc::NewPage(void)
  1033.     {
  1034.     FDirtySet(TRUE);
  1035.     return m_pPG->PageInsert(0);
  1036.     }
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044. /*
  1045.  * CPatronDoc::DeletePage
  1046.  *
  1047.  * Purpose:
  1048.  *  Deletes the current page from the document.
  1049.  *
  1050.  * Parameters:
  1051.  *  None
  1052.  *
  1053.  * Return Value:
  1054.  *  UINT            Index of the now current page.
  1055.  */
  1056.  
  1057. UINT CPatronDoc::DeletePage(void)
  1058.     {
  1059.     FDirtySet(TRUE);
  1060.     return m_pPG->PageDelete(0);
  1061.     }
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069. /*
  1070.  * CPatronDoc::NextPage
  1071.  *
  1072.  * Purpose:
  1073.  *  Shows the next page in the pages window.
  1074.  *
  1075.  * Parameters:
  1076.  *  None
  1077.  *
  1078.  * Return Value:
  1079.  *  UINT            Index of the new page.
  1080.  */
  1081.  
  1082. UINT CPatronDoc::NextPage(void)
  1083.     {
  1084.     UINT        iPage;
  1085.  
  1086.     iPage=m_pPG->CurPageGet();
  1087.     return m_pPG->CurPageSet(++iPage);
  1088.     }
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096. /*
  1097.  * CPatronDoc::PreviousPage
  1098.  *
  1099.  * Purpose:
  1100.  *  Shows the previous page in the pages window.
  1101.  *
  1102.  * Parameters:
  1103.  *  None
  1104.  *
  1105.  * Return Value:
  1106.  *  UINT            Index of the new page.
  1107.  */
  1108.  
  1109. UINT CPatronDoc::PreviousPage(void)
  1110.     {
  1111.     UINT        iPage;
  1112.  
  1113.     //If iPage is zero, then we wrap around to the end.
  1114.     iPage=m_pPG->CurPageGet();
  1115.     return m_pPG->CurPageSet(--iPage);
  1116.     }
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123. /*
  1124.  * CPatronDoc::FirstPage
  1125.  *
  1126.  * Purpose:
  1127.  *  Shows the first page page in the pages window.
  1128.  *
  1129.  * Parameters:
  1130.  *  None
  1131.  *
  1132.  * Return Value:
  1133.  *  UINT            Index of the new page.
  1134.  */
  1135.  
  1136. UINT CPatronDoc::FirstPage(void)
  1137.     {
  1138.     return m_pPG->CurPageSet(0);
  1139.     }
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146. /*
  1147.  * CPatronDoc::LastPage
  1148.  *
  1149.  * Purpose:
  1150.  *  Shows the last page in the pages window.
  1151.  *
  1152.  * Parameters:
  1153.  *  None
  1154.  *
  1155.  * Return Value:
  1156.  *  UINT            Index of the last page.
  1157.  */
  1158.  
  1159. UINT CPatronDoc::LastPage(void)
  1160.     {
  1161.     return m_pPG->CurPageSet(-1);
  1162.     }
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168. //CHAPTER9MOD
  1169.  
  1170. /*
  1171.  * CPatronDoc::Rename
  1172.  *
  1173.  * Purpose:
  1174.  *  Overrides the normal rename to include notification of tenants
  1175.  *  in this document of the new name.  This is so embedded objects
  1176.  *  are told the correct name through IOleObject::SetHostNames.
  1177.  *
  1178.  * Parameters:
  1179.  *  pszFile         LPSTR to the new filename.
  1180.  *
  1181.  * Return Value:
  1182.  *  None
  1183.  */
  1184.  
  1185. void CPatronDoc::Rename(LPSTR pszFile)
  1186.     {
  1187.     //We don't need to change the base class, just augment...
  1188.     CDocument::Rename(pszFile);
  1189.     m_pPG->NotifyTenantsOfRename(pszFile, NULL);
  1190.     return;
  1191.     }
  1192.  
  1193.  
  1194.  
  1195.  
  1196.  
  1197. /*
  1198.  * CPatronDoc::FInsertObject
  1199.  *
  1200.  * Purpose:
  1201.  *  Retrieves a CLSID or a filename from the Insert Object dialog box
  1202.  *  and creates an object using those identifiers.
  1203.  *
  1204.  * Parameters:
  1205.  *  hWndFrame       HWND of the main window
  1206.  *
  1207.  * Return Value:
  1208.  *  BOOL            TRUE if successful, FALSE otherwise.
  1209.  */
  1210.  
  1211. BOOL CPatronDoc::FInsertObject(HWND hWndFrame)
  1212.     {
  1213.     OLEUIINSERTOBJECT   io;
  1214.     DWORD               dwData=0;
  1215.     char                szFile[CCHPATHMAX];
  1216.     UINT                uTemp;
  1217.     BOOL                fRet=FALSE;
  1218.  
  1219.     if (NULL==m_pPG)
  1220.         return FALSE;
  1221.  
  1222.     _fmemset(&io, 0, sizeof(io));
  1223.  
  1224.     io.cbStruct=sizeof(io);
  1225.     io.hWndOwner=hWndFrame;
  1226.  
  1227.     szFile[0]=0;
  1228.     io.lpszFile=szFile;
  1229.     io.cchFile=sizeof(szFile);
  1230.  
  1231.     io.dwFlags=IOF_SELECTCREATENEW | IOF_DISABLELINK;
  1232.  
  1233.     uTemp=OleUIInsertObject(&io);
  1234.  
  1235.     if (OLEUI_OK==uTemp)
  1236.         {
  1237.         TENANTTYPE      tType;
  1238.         LPVOID          pv;
  1239.         FORMATETC       fe;
  1240.  
  1241.         SETDefFormatEtc(fe, 0, TYMED_NULL);
  1242.  
  1243.         if (io.dwFlags & IOF_SELECTCREATENEW)
  1244.             {
  1245.             tType=TENANTTYPE_EMBEDDEDOBJECT;
  1246.             pv=(LPVOID)&io.clsid;
  1247.             }
  1248.         else
  1249.             {
  1250.             tType=TENANTTYPE_EMBEDDEDFILE;
  1251.             pv=(LPVOID)szFile;
  1252.             }
  1253.  
  1254.         if ((io.dwFlags & IOF_CHECKDISPLAYASICON) && NULL!=io.hMetaPict)
  1255.             {
  1256.             fe.dwAspect=DVASPECT_ICON;
  1257.             dwData=(DWORD)(UINT)io.hMetaPict;
  1258.             }
  1259.  
  1260.         fRet=m_pPG->TenantCreate(tType, pv, &fe, NULL, dwData);
  1261.  
  1262.         //Free this regardless of what we do with it.
  1263.         if (NULL!=io.hMetaPict)
  1264.             OleUIMetafilePictIconFree(io.hMetaPict);
  1265.  
  1266.         if (fRet)
  1267.             {
  1268.             //Disable Printer Setup once we've created a tenant.
  1269.             m_fPrintSetup=FALSE;
  1270.             FDirtySet(TRUE);
  1271.             }
  1272.         }
  1273.  
  1274.     return fRet;
  1275.     }
  1276.  
  1277.  
  1278.  
  1279.  
  1280. /*
  1281.  * CPatronDoc::ActivateObject
  1282.  *
  1283.  * Purpose:
  1284.  *  Executes a verb on the currently selected object.
  1285.  *
  1286.  * Parameters:
  1287.  *  iVerb           UINT of the selected verb.
  1288.  *
  1289.  * Return Value:
  1290.  *  None
  1291.  */
  1292.  
  1293. void CPatronDoc::ActivateObject(UINT iVerb)
  1294.     {
  1295.     m_pPG->ActivateObject(iVerb);
  1296.     return;
  1297.     }
  1298.  
  1299.  
  1300. //End CHAPTER9MOD
  1301.